Skip to content

feat: run the Spock-backed Instagram demo through Uhura#9

Merged
softmarshmallow merged 4 commits into
mainfrom
feature/instagram-spock-uhura
Jul 14, 2026
Merged

feat: run the Spock-backed Instagram demo through Uhura#9
softmarshmallow merged 4 commits into
mainfrom
feature/instagram-spock-uhura

Conversation

@softmarshmallow

@softmarshmallow softmarshmallow commented Jul 14, 2026

Copy link
Copy Markdown
Member

Summary

  • add a richer Spock Instagram authority with realistic seed data and media
  • advance the Uhura subsystem to the matching Editor and Play demo
  • pin the Uhura submodule to merged uhura/main commit 5b45eaa
  • add a supervised umbrella runner for Spock and Uhura
  • allow a browser-hosted Uhura client to use Spock GraphQL, RPC, identity, and media
  • align frontend tooling on Node 24 and pinned package-manager versions

Runtime scope

The only Spock runtime change is permissive CORS across the loopback-bound v0 development authority. This deliberately extends RFD 0015's same-origin Studio posture so a separately hosted Uhura prototype can call Spock with JSON and X-Spock-Actor headers. The behavior has a protocol preflight regression test.

The companion Uhura language/runtime changes landed in gridaco/uhura#1. This PR's submodule gitlink now references that PR's merge commit on uhura/main.

Known limits

  • --spock-port does not rewrite the Uhura provider configuration; the project manifest must address the same port.
  • launcher readiness covers the two HTTP hosts, not successful Play-provider boot.
  • a clean checkout must build the ignored Uhura Wasm web package once; the runner validates required artifacts and reports the build command.

Verification

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace
  • cargo run -p spock-cli -- check examples/instagram-poc/app.spock
  • Studio frozen install and production build
  • Instagram client clean install and TypeScript check
  • bash -n scripts/spock-uhura.sh and ShellCheck
  • default-port umbrella runner browser smoke test
  • verified the former Uhura PR head and merged-main gitlink target have identical source trees

Add stored video objects, private saves, multi-frame stories, whitespace-safe comments, and a richer relational seed; advance Uhura to the fully Spock-backed client.
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@softmarshmallow, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d639928c-bcf1-4b76-b262-20a0ac7ed5b2

📥 Commits

Reviewing files that changed from the base of the PR and between e1a8eb6 and b6c8be5.

📒 Files selected for processing (1)
  • uhura

Walkthrough

The PR standardizes Node.js 24 tooling, enables permissive runtime CORS, adds an Instagram Spock authority with seeded data, and introduces a supervised script for running Spock and Uhura together.

Changes

Uhura and Spock integration

Layer / File(s) Summary
Node.js 24 tooling alignment
.nvmrc, .github/workflows/npm.yml, crates/spock-runtime/studio/*, examples/instagram/client/*, docs/rfd/0020-distribution.md
CI, studio tooling, the Instagram client, and distribution documentation now use Node.js 24 and pinned package-manager settings.
Browser CORS support
crates/spock-runtime/Cargo.toml, crates/spock-runtime/src/http.rs, crates/spock-runtime/tests/http.rs
The runtime applies permissive CORS middleware and tests GraphQL preflight responses.
Instagram proof-of-concept authority
examples/instagram-poc/app.spock
Adds social data tables, authenticated commands, validation, media handling, and deterministic seed data.
Supervised Spock–Uhura runner
scripts/spock-uhura.sh, README.md, uhura
Adds local port/configuration validation, artifact checks, launcher builds, readiness polling, coordinated shutdown, composition documentation, and an updated Uhura submodule reference.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Runner as spock-uhura.sh
  participant Spock as spock-cli
  participant Uhura as uhura-cli
  Runner->>Spock: Build and start Spock
  Runner->>Spock: Wait for /~health
  Runner->>Uhura: Start the Uhura editor
  Runner->>Uhura: Wait for the editor URL
  Runner->>Spock: Stop Spock when Uhura exits
  Runner->>Uhura: Stop Uhura when Spock exits
Loading

Possibly related PRs

  • gridaco/spock#6: Updates documentation and topology for the Uhura submodule used by this composition workflow.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed It clearly summarizes the main change: running the Spock-backed Instagram demo through Uhura.
Description check ✅ Passed The description matches the changeset and accurately covers the demo, runner, CORS, and tooling updates.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/instagram-spock-uhura

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@softmarshmallow softmarshmallow marked this pull request as ready for review July 14, 2026 07:30
@softmarshmallow softmarshmallow merged commit 3f1e40b into main Jul 14, 2026
1 check passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
examples/instagram-poc/app.spock (1)

148-159: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add unique(post, position) to carousel_slide.

story enforces unique(author, position) for exactly this "deterministic ordered sequence" need (line 90), but carousel_slide doesn't have the equivalent unique(post, position). Nothing writes carousel slides today, but the asymmetry with the sibling table is worth closing now while it's cheap.

🔧 Proposed fix
 table carousel_slide {
   key id: uuid = auto
   /// The carousel post this slide belongs to.
   post: post on delete cascade
   /// Slide order, 1-based.
   position: int
   /// The slide image stored in Spock's byte plane.
   file: storage_object
   /// Alt text for the slide.
   alt: text
+  unique (post, position)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/instagram-poc/app.spock` around lines 148 - 159, Add a composite
uniqueness constraint on post and position to the carousel_slide table, matching
the existing unique(author, position) pattern used by story. Keep the current
fields and relationships unchanged.
crates/spock-runtime/studio/.npmrc (1)

1-3: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Move pnpm version-policy settings out of .npmrc. manage-package-manager-versions and package-manager-strict-version are removed in pnpm 11, and .npmrc there is limited to auth/registry settings. Put these in pnpm-workspace.yaml before bumping the pnpm pin.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/spock-runtime/studio/.npmrc` around lines 1 - 3, Remove
manage-package-manager-versions and package-manager-strict-version from .npmrc,
then add the equivalent pnpm version-policy settings to pnpm-workspace.yaml
using its supported configuration keys before updating the pinned pnpm version.
Keep engine-strict in .npmrc.
examples/instagram/client/package.json (1)

5-8: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Enforce the npm pin in the example setup

packageManager here is only metadata: examples/instagram/client/README.md tells contributors to run nvm use and npm install, and .npmrc only sets engine-strict=true for Node. Add Corepack or a devEngines.packageManager check if npm@11.16.0 is required.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/instagram/client/package.json` around lines 5 - 8, Update the
examples/instagram/client setup to enforce the required npm@11.16.0 version
rather than relying on the packageManager metadata; add an appropriate Corepack
configuration or devEngines.packageManager check, and ensure the existing README
npm install workflow triggers that validation.

Source: MCP tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/instagram-poc/app.spock`:
- Around line 415-800: Audit every file("./seed/...") reference in the seed
block, identify the asset missing from the examples/instagram-poc/seed
collection, and either add that asset or correct the reference to an existing
file. Preserve the intended media mapping for the associated story, post,
carousel slide, or profile field, especially the story declarations such as
lena_story and mira_story.

In `@uhura`:
- Line 1: Restore and check in the generated web Wasm artifacts under the Uhura
submodule, specifically uhura_wasm.js and uhura_wasm_bg.wasm expected by
scripts/spock-uhura.sh, or update the launcher’s preflight requirement if those
artifacts are intentionally no longer needed; ensure a clean checkout passes the
launcher preflight.

---

Nitpick comments:
In `@crates/spock-runtime/studio/.npmrc`:
- Around line 1-3: Remove manage-package-manager-versions and
package-manager-strict-version from .npmrc, then add the equivalent pnpm
version-policy settings to pnpm-workspace.yaml using its supported configuration
keys before updating the pinned pnpm version. Keep engine-strict in .npmrc.

In `@examples/instagram-poc/app.spock`:
- Around line 148-159: Add a composite uniqueness constraint on post and
position to the carousel_slide table, matching the existing unique(author,
position) pattern used by story. Keep the current fields and relationships
unchanged.

In `@examples/instagram/client/package.json`:
- Around line 5-8: Update the examples/instagram/client setup to enforce the
required npm@11.16.0 version rather than relying on the packageManager metadata;
add an appropriate Corepack configuration or devEngines.packageManager check,
and ensure the existing README npm install workflow triggers that validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e1304f4b-31c0-4ba2-a0f2-fdfc3dbabd49

📥 Commits

Reviewing files that changed from the base of the PR and between 4b871a9 and e1a8eb6.

⛔ Files ignored due to path filters (40)
  • Cargo.lock is excluded by !**/*.lock
  • crates/spock-runtime/studio/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • examples/instagram-poc/seed/avatar-ayla.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/avatar-june.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/avatar-kenji.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/avatar-lena.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/avatar-marco.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/avatar-mira.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/avatar-nils.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/avatar-priya.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/avatar-theo.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-ayla-ferry.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-june-lookbook.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-kenji-copper.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-lena-glaze.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-marco-baja-1.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-marco-baja-2.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-marco-baja-3.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-mira-ferry.mp4 is excluded by !**/*.mp4
  • examples/instagram-poc/seed/media-nils-aurora-poster.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-nils-aurora.mp4 is excluded by !**/*.mp4
  • examples/instagram-poc/seed/media-priya-starter.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-theo-court.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/media-theo-court.mp4 is excluded by !**/*.mp4
  • examples/instagram-poc/seed/thumb-lena-1.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-lena-2.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-lena-3.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-lena-4.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-lena-5.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-lena-6.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-lena-7.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-lena-8.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-lena-9.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-mira-1.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-mira-2.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-mira-3.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-mira-4.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-mira-5.jpg is excluded by !**/*.jpg
  • examples/instagram-poc/seed/thumb-mira-6.jpg is excluded by !**/*.jpg
  • examples/instagram/client/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (16)
  • .github/workflows/npm.yml
  • .nvmrc
  • README.md
  • crates/spock-runtime/Cargo.toml
  • crates/spock-runtime/src/http.rs
  • crates/spock-runtime/studio/.npmrc
  • crates/spock-runtime/studio/README.md
  • crates/spock-runtime/studio/package.json
  • crates/spock-runtime/tests/http.rs
  • docs/rfd/0020-distribution.md
  • examples/instagram-poc/app.spock
  • examples/instagram/client/.npmrc
  • examples/instagram/client/README.md
  • examples/instagram/client/package.json
  • scripts/spock-uhura.sh
  • uhura

Comment on lines +415 to +800
seed {
// People use stable ids because the Play provider's actor header is Mira's
// UUID. Every person has a complete profile; no profile count is seeded.
mira = user { id: "10000000-0000-4000-8000-000000000001",
username: "mira.santos", display_name: "Mira Santos",
avatar: file("./seed/avatar-mira.jpg"), avatar_alt: "Mira Santos",
bio: "Food and travel photographer in Lisbon. Usually awake before the trams." }
lena = user { id: "10000000-0000-4000-8000-000000000002",
username: "lena.holt", display_name: "Lena Holt",
avatar: file("./seed/avatar-lena.jpg"), avatar_alt: "Lena Holt",
bio: "Ceramics and slow mornings. Small-batch studio work from Portland." }
marco = user { id: "10000000-0000-4000-8000-000000000003",
username: "marco.reyes", display_name: "Marco Reyes",
avatar: file("./seed/avatar-marco.jpg"), avatar_alt: "Marco Reyes",
bio: "Surf photographer, road-trip cook, and reluctant morning person." }
nils = user { id: "10000000-0000-4000-8000-000000000004",
username: "nils.bergman", display_name: "Nils Bergman",
avatar: file("./seed/avatar-nils.jpg"), avatar_alt: "Nils Bergman",
bio: "Night skies and northern water, filmed around Tromsø." }
priya = user { id: "10000000-0000-4000-8000-000000000005",
username: "priya.raman", display_name: "Priya Raman",
avatar: file("./seed/avatar-priya.jpg"), avatar_alt: "Priya Raman",
bio: "Bread notebook, tiny kitchen, stubborn sourdough starter." }
ayla = user { id: "10000000-0000-4000-8000-000000000006",
username: "ayla.demir", display_name: "Ayla Demir",
avatar: file("./seed/avatar-ayla.jpg"), avatar_alt: "Ayla Demir",
bio: "Istanbul by ferry. Architecture, tea, and ordinary light." }
june = user { id: "10000000-0000-4000-8000-000000000007",
username: "june.park", display_name: "June Park",
avatar: file("./seed/avatar-june.jpg"), avatar_alt: "June Park",
bio: "Natural-fiber clothes made in a very crowded studio." }
theo = user { id: "10000000-0000-4000-8000-000000000008",
username: "theo.okafor", display_name: "Theo Okafor",
avatar: file("./seed/avatar-theo.jpg"), avatar_alt: "Theo Okafor",
bio: "Murals, community courts, and an unreliable jump shot." }
kenji = user { id: "10000000-0000-4000-8000-000000000009",
username: "kenji.rides", display_name: "Kenji Tanaka",
avatar: file("./seed/avatar-kenji.jpg"), avatar_alt: "Kenji Tanaka",
bio: "Long climbs, quiet roads, and coffee at the turnaround." }

// Directed relationships: every Followers/Following count and list comes
// from these edges. Mira follows six people and has four followers.
follow { follower: mira, followed: lena }
follow { follower: mira, followed: marco }
follow { follower: mira, followed: priya }
follow { follower: mira, followed: ayla }
follow { follower: mira, followed: june }
follow { follower: mira, followed: kenji }
follow { follower: lena, followed: mira }
follow { follower: lena, followed: marco }
follow { follower: lena, followed: priya }
follow { follower: lena, followed: june }
follow { follower: lena, followed: theo }
follow { follower: marco, followed: lena }
follow { follower: marco, followed: nils }
follow { follower: marco, followed: ayla }
follow { follower: marco, followed: kenji }
follow { follower: nils, followed: lena }
follow { follower: nils, followed: marco }
follow { follower: nils, followed: theo }
follow { follower: priya, followed: mira }
follow { follower: priya, followed: lena }
follow { follower: priya, followed: ayla }
follow { follower: priya, followed: june }
follow { follower: ayla, followed: lena }
follow { follower: ayla, followed: priya }
follow { follower: ayla, followed: june }
follow { follower: june, followed: mira }
follow { follower: june, followed: lena }
follow { follower: june, followed: ayla }
follow { follower: june, followed: theo }
follow { follower: theo, followed: mira }
follow { follower: theo, followed: lena }
follow { follower: theo, followed: june }
follow { follower: kenji, followed: lena }
follow { follower: kenji, followed: marco }
follow { follower: kenji, followed: nils }
follow { follower: kenji, followed: priya }

// Twelve active frames across six tray authors. Mira, Lena, and Marco each
// carry a three-frame sequence so the story player exercises progress and
// next/previous navigation. Story-view rows below make Lena, Marco, and June
// unseen to Mira while Priya and Kenji are already seen.
mira_story = story {
id: "30000000-0000-4000-8000-000000000001", author: mira, position: 1,
media_file: file("./seed/thumb-mira-1.jpg"),
media_alt: "Pastéis de nata cooling on a marble counter",
caption: "Breakfast before the first tram",
published_at: "2026-07-13T15:10:00Z" }
mira_story_tram = story {
id: "30000000-0000-4000-8000-000000000008", author: mira, position: 2,
media_file: file("./seed/thumb-mira-2.jpg"),
media_alt: "Tram rails catching the first light in Lisbon",
caption: "Then the city wakes",
published_at: "2026-07-13T15:22:00Z" }
mira_story_market = story {
id: "30000000-0000-4000-8000-000000000009", author: mira, position: 3,
media_file: file("./seed/thumb-mira-3.jpg"),
media_alt: "Crates of citrus stacked at the morning market",
caption: "Saturday palette",
published_at: "2026-07-13T15:38:00Z" }
lena_story = story {
id: "30000000-0000-4000-8000-000000000002", author: lena, position: 1,
media_file: file("./seed/thumb-lena-7.jpg"),
media_alt: "Lena throwing a tall clay cylinder",
caption: "One pull, no edits",
published_at: "2026-07-13T14:55:00Z" }
lena_story_glazes = story {
id: "30000000-0000-4000-8000-000000000010", author: lena, position: 2,
media_file: file("./seed/thumb-lena-8.jpg"),
media_alt: "Rows of glaze buckets labelled by firing cone",
caption: "The unglamorous half of studio day",
published_at: "2026-07-13T15:08:00Z" }
lena_story_studio = story {
id: "30000000-0000-4000-8000-000000000011", author: lena, position: 3,
media_file: file("./seed/thumb-lena-9.jpg"),
media_alt: "Morning light crossing a clean ceramics workbench",
caption: "Reset for tomorrow",
published_at: "2026-07-13T15:24:00Z" }
marco_story = story {
id: "30000000-0000-4000-8000-000000000004", author: marco, position: 1,
media_file: file("./seed/media-marco-baja-2.jpg"),
media_alt: "Campfire on a bluff above the break",
caption: "Last night at camp",
published_at: "2026-07-13T14:40:00Z" }
marco_story_swell = story {
id: "30000000-0000-4000-8000-000000000012", author: marco, position: 2,
media_file: file("./seed/media-marco-baja-1.jpg"),
media_alt: "Long left-hand wave peeling along a desert point",
caption: "It finally arrived",
published_at: "2026-07-13T14:52:00Z" }
marco_story_dawn = story {
id: "30000000-0000-4000-8000-000000000013", author: marco, position: 3,
media_file: file("./seed/media-marco-baja-3.jpg"),
media_alt: "Surfboard fins silhouetted against a Baja sunrise",
caption: "Pack up before the wind",
published_at: "2026-07-13T15:04:00Z" }
priya_story = story {
id: "30000000-0000-4000-8000-000000000005", author: priya, position: 1,
media_file: file("./seed/media-priya-starter.jpg"),
media_alt: "Freshly sliced sourdough loaf",
caption: "Still warm",
published_at: "2026-07-13T14:20:00Z" }
june_story = story {
id: "30000000-0000-4000-8000-000000000006", author: june, position: 1,
media_file: file("./seed/media-june-lookbook.jpg"),
media_alt: "Linen garments arranged by shade",
caption: "Fitting day",
published_at: "2026-07-13T13:50:00Z" }
kenji_story = story {
id: "30000000-0000-4000-8000-000000000007", author: kenji, position: 1,
media_file: file("./seed/media-kenji-copper.jpg"),
media_alt: "Road bike at Copper Pass",
caption: "Worth the climb",
published_at: "2026-07-13T13:15:00Z" }
story_view { viewer: mira, story: mira_story }
story_view { viewer: mira, story: mira_story_tram }
story_view { viewer: mira, story: mira_story_market }
story_view { viewer: mira, story: priya_story }
story_view { viewer: mira, story: kenji_story }

// Eight current home-feed posts. Their engagement totals below are exactly
// the number of real like/comment rows, not seeded headline numbers.
lena_glaze = post {
id: "20000000-0000-4000-8000-000000000001", author: lena,
caption: "New copper-red test tiles out of the kiln. Cone 10, heavy reduction — the speckle finally behaved.",
published_at: "2026-07-13T13:00:00Z",
media_kind: "image", media_file: file("./seed/media-lena-glaze.jpg"),
media_alt: "Grid of copper-red glaze test tiles on a maple bench" }
marco_baja = post {
id: "20000000-0000-4000-8000-000000000002", author: marco,
caption: "Three days down the Baja coast. Swell arrived on the last morning, as it always does.",
published_at: "2026-07-13T10:00:00Z", media_kind: "carousel" }
nils_aurora = post {
id: "20000000-0000-4000-8000-000000000003", author: nils,
caption: "Aurora over the fjord last night — the whole sky was breathing.",
published_at: "2026-07-13T06:00:00Z", media_kind: "video",
media_file: file("./seed/media-nils-aurora-poster.jpg"),
video_file: file("./seed/media-nils-aurora.mp4"),
media_alt: "Green aurora curtains over a dark fjord" }
priya_starter = post {
id: "20000000-0000-4000-8000-000000000004", author: priya,
caption: "Day 400 of the starter. She's earned a name: Clint Yeastwood.",
published_at: "2026-07-12T23:00:00Z", media_kind: "image",
media_file: file("./seed/media-priya-starter.jpg"),
media_alt: "Open crumb of a sourdough loaf, sliced on a flour-dusted board" }
ayla_ferry = post {
id: "20000000-0000-4000-8000-000000000005", author: ayla,
caption: "Morning ferry across the Bosphorus. Tea, gulls, and nowhere to be until noon.",
published_at: "2026-07-12T16:00:00Z", media_kind: "image",
media_file: file("./seed/media-ayla-ferry.jpg"),
media_alt: "Ferry deck railing over blue water, city skyline behind" }
june_lookbook = post {
id: "20000000-0000-4000-8000-000000000006", author: june,
caption: "Studio lookbook, page one. Linen in every weight we could mill.",
published_at: "2026-07-12T10:00:00Z", media_kind: "image",
media_file: file("./seed/media-june-lookbook.jpg"),
media_alt: "Folded linen garments stacked by shade on a workbench" }
theo_court = post {
id: "20000000-0000-4000-8000-000000000007", author: theo,
caption: "Finished the mural at the 9th street court. Paint holds up better than my jumper.",
published_at: "2026-07-11T17:00:00Z", media_kind: "video",
media_file: file("./seed/media-theo-court.jpg"),
video_file: file("./seed/media-theo-court.mp4"),
media_alt: "Basketball court painted with bold geometric shapes" }
kenji_copper = post {
id: "20000000-0000-4000-8000-000000000008", author: kenji,
caption: "120km of switchbacks and one very smug goat. Copper Pass, you were worth it.",
published_at: "2026-07-11T11:00:00Z", media_kind: "image",
media_file: file("./seed/media-kenji-copper.jpg"),
media_alt: "Road bike leaning on a stone wall at a mountain pass" }

// Lena's and Mira's former decorative thumbnails are now genuine posts.
// They appear in profile grids and can open the same post-detail design as
// feed posts; show_in_feed keeps this history out of the compact home feed.
lena_bowls = post { id: "21000000-0000-4000-8000-000000000001", author: lena,
caption: "Copper glaze in close-up, before the wax cooled.",
published_at: "2026-07-10T14:00:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-1.jpg"), media_alt: "Copper-red glaze tiles" }
lena_greenware = post { id: "21000000-0000-4000-8000-000000000002", author: lena,
caption: "A quiet stack of bowls waiting for bisque firing.",
published_at: "2026-07-08T16:00:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-2.jpg"), media_alt: "Stack of unglazed bowls" }
lena_kiln = post { id: "21000000-0000-4000-8000-000000000003", author: lena,
caption: "Kiln Tetris, level thirty-seven.",
published_at: "2026-07-05T11:30:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-3.jpg"), media_alt: "Kiln shelf mid-load" }
lena_celadon = post { id: "21000000-0000-4000-8000-000000000004", author: lena,
caption: "Celadon tests after a slower cool-down.",
published_at: "2026-07-02T09:15:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-4.jpg"), media_alt: "Celadon test cups" }
lena_clay = post { id: "21000000-0000-4000-8000-000000000005", author: lena,
caption: "Fresh reclaim, wedged and ready for tomorrow.",
published_at: "2026-06-28T18:40:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-5.jpg"), media_alt: "Wedging table with fresh clay" }
lena_plates = post { id: "21000000-0000-4000-8000-000000000006", author: lena,
caption: "Dinner plates with just enough iron speckle.",
published_at: "2026-06-24T13:00:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-6.jpg"), media_alt: "Iron-speckled dinner plates" }
lena_throwing = post { id: "21000000-0000-4000-8000-000000000007", author: lena,
caption: "Pulling one tall cylinder before lunch.",
published_at: "2026-06-19T16:20:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-7.jpg"), media_alt: "Throwing a tall cylinder" }
lena_buckets = post { id: "21000000-0000-4000-8000-000000000008", author: lena,
caption: "Labelling day. Future me will be grateful.",
published_at: "2026-06-12T10:10:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-8.jpg"), media_alt: "Glaze buckets labelled by cone" }
lena_morning = post { id: "21000000-0000-4000-8000-000000000009", author: lena,
caption: "Seven o'clock light across the clean bench.",
published_at: "2026-06-03T14:05:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-lena-9.jpg"), media_alt: "Morning light across the studio bench" }

mira_pasteis = post { id: "22000000-0000-4000-8000-000000000001", author: mira,
caption: "The batch that vanished before I finished the coffee.",
published_at: "2026-07-09T07:30:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-mira-1.jpg"), media_alt: "Pastéis de nata on a marble counter" }
mira_tram = post { id: "22000000-0000-4000-8000-000000000002", author: mira,
caption: "Rails holding the first light on Rua da Conceição.",
published_at: "2026-07-04T05:45:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-mira-2.jpg"), media_alt: "Tram rails catching dawn light" }
mira_citrus = post { id: "22000000-0000-4000-8000-000000000003", author: mira,
caption: "Saturday citrus, arranged better than any still life.",
published_at: "2026-06-29T08:20:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-mira-3.jpg"), media_alt: "Market citrus stacked in crates" }
mira_tiles = post { id: "22000000-0000-4000-8000-000000000004", author: mira,
caption: "Blue after blue after blue.",
published_at: "2026-06-21T15:10:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-mira-4.jpg"), media_alt: "Tiled facade in alternating blues" }
mira_sardines = post { id: "22000000-0000-4000-8000-000000000005", author: mira,
caption: "Sardines, smoke, lemon. Nothing else needed.",
published_at: "2026-06-13T20:15:00Z", show_in_feed: false,
media_kind: "image", media_file: file("./seed/thumb-mira-5.jpg"), media_alt: "Grilled sardines over coals" }
mira_ferry = post { id: "22000000-0000-4000-8000-000000000006", author: mira,
caption: "The last ferry left a gold line all the way home.",
published_at: "2026-06-01T19:50:00Z", show_in_feed: false,
media_kind: "video", media_file: file("./seed/thumb-mira-6.jpg"),
video_file: file("./seed/media-mira-ferry.mp4"), media_alt: "Ferry wake at golden hour" }

// Real tag edges. Tagged grids reuse these posts and their media rather than
// carrying separate decorative thumbnails. Mira's tagged post is Marco's
// Baja carousel; its first slide is therefore her tagged-grid thumbnail.
post_tag { post: marco_baja, person: mira }
post_tag { post: june_lookbook, person: ayla }
post_tag { post: theo_court, person: june }
post_tag { post: priya_starter, person: lena }
post_tag { post: kenji_copper, person: marco }
post_tag { post: lena_glaze, person: theo }

// Marco's carousel, in slide order.
carousel_slide { post: marco_baja, position: 1, file: file("./seed/media-marco-baja-1.jpg"),
alt: "Long left-hand wave peeling along a desert point" }
carousel_slide { post: marco_baja, position: 2, file: file("./seed/media-marco-baja-2.jpg"),
alt: "Campfire on the bluff above the break at dusk" }
carousel_slide { post: marco_baja, position: 3, file: file("./seed/media-marco-baja-3.jpg"),
alt: "Board fins silhouetted against the sunrise" }

// Real comment rows. Feed cards and details count these rows.
comment { post: lena_glaze, author: kenji, created_at: "2026-07-13T13:28:00Z",
body: "That copper red is unreal. What cone are you firing to?" }
comment { post: lena_glaze, author: priya, created_at: "2026-07-13T13:35:00Z",
body: "The third tile down — that speckle! Saving this for glaze inspiration." }
comment { post: lena_glaze, author: june, created_at: "2026-07-13T13:42:00Z",
body: "Would buy the whole batch honestly. Seconds sale when?" }
comment { post: lena_glaze, author: theo, created_at: "2026-07-13T13:51:00Z",
body: "These would look wild as a court-side mosaic. Collab?" }
comment { post: marco_baja, author: kenji, created_at: "2026-07-13T10:18:00Z",
body: "That road looks nearly as good as the wave." }
comment { post: marco_baja, author: ayla, created_at: "2026-07-13T10:26:00Z",
body: "Frame two belongs on a wall." }
comment { post: nils_aurora, author: mira, created_at: "2026-07-13T06:22:00Z",
body: "The reflection makes this. Beautiful." }
comment { post: priya_starter, author: lena, created_at: "2026-07-13T12:40:00Z",
body: "Clint looks extremely healthy." }
comment { post: priya_starter, author: theo, created_at: "2026-07-13T13:05:00Z",
body: "I volunteer for quality control." }
comment { post: ayla_ferry, author: mira, created_at: "2026-07-13T06:00:00Z",
body: "That blue is perfect." }
comment { post: june_lookbook, author: ayla, created_at: "2026-07-12T22:35:00Z",
body: "The warm grey set, please." }
comment { post: theo_court, author: june, created_at: "2026-07-12T06:10:00Z",
body: "This completely changes the block." }
comment { post: kenji_copper, author: marco, created_at: "2026-07-12T00:20:00Z",
body: "Goat photo or it did not happen." }

// Real like edges. Mira has already liked Kenji's post; like toggles change
// the row set and therefore the displayed count with no synchronization job.
like { user: marco, post: lena_glaze }
like { user: nils, post: lena_glaze }
like { user: priya, post: lena_glaze }
like { user: ayla, post: lena_glaze }
like { user: june, post: lena_glaze }
like { user: theo, post: lena_glaze }
like { user: kenji, post: lena_glaze }
like { user: lena, post: marco_baja }
like { user: nils, post: marco_baja }
like { user: priya, post: marco_baja }
like { user: ayla, post: marco_baja }
like { user: kenji, post: marco_baja }
like { user: lena, post: nils_aurora }
like { user: marco, post: nils_aurora }
like { user: priya, post: nils_aurora }
like { user: ayla, post: nils_aurora }
like { user: june, post: nils_aurora }
like { user: lena, post: priya_starter }
like { user: marco, post: priya_starter }
like { user: nils, post: priya_starter }
like { user: ayla, post: priya_starter }
like { user: june, post: priya_starter }
like { user: theo, post: priya_starter }
like { user: kenji, post: priya_starter }
like { user: lena, post: ayla_ferry }
like { user: marco, post: ayla_ferry }
like { user: priya, post: ayla_ferry }
like { user: june, post: ayla_ferry }
like { user: lena, post: june_lookbook }
like { user: priya, post: june_lookbook }
like { user: ayla, post: june_lookbook }
like { user: theo, post: june_lookbook }
like { user: marco, post: theo_court }
like { user: ayla, post: theo_court }
like { user: june, post: theo_court }
like { user: kenji, post: theo_court }
like { user: mira, post: kenji_copper }
like { user: lena, post: kenji_copper }
like { user: marco, post: kenji_copper }
like { user: nils, post: kenji_copper }
like { user: priya, post: kenji_copper }
like { user: ayla, post: kenji_copper }
like { user: june, post: kenji_copper }
like { user: theo, post: kenji_copper }
like { user: mira, post: lena_bowls }
like { user: priya, post: lena_bowls }
like { user: june, post: lena_greenware }
like { user: theo, post: lena_kiln }
like { user: lena, post: mira_pasteis }
like { user: priya, post: mira_pasteis }
like { user: june, post: mira_tram }
like { user: kenji, post: mira_ferry }

// Private saved-library state. Mira's two rows make the default actor's
// Saved view useful immediately; Priya's row proves actor switching does not
// leak one person's library into another's. No public count derives from it.
save { user: mira, post: marco_baja }
save { user: mira, post: nils_aurora }
save { user: priya, post: lena_glaze }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify every seed file referenced in app.spock exists on disk.
set -euo pipefail
grep -oP 'file\("\./seed/[^"]+"\)' examples/instagram-poc/app.spock \
  | sed -E 's#file\("\./seed/([^"]+)"\)#\1#' \
  | sort -u \
  | while read -r name; do
      if [ ! -f "examples/instagram-poc/seed/$name" ]; then
        echo "MISSING: $name"
      fi
    done

Repository: gridaco/spock

Length of output: 162


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import re, pathlib
app = pathlib.Path("examples/instagram-poc/app.spock").read_text()
refs = sorted(set(re.findall(r'file\("\./seed/([^"]+)"\)', app)))
seed_dir = pathlib.Path("examples/instagram-poc/seed")
missing = [r for r in refs if not (seed_dir / r).is_file()]
print("refs", len(refs))
print("missing", len(missing))
for m in missing:
    print(m)
PY

Repository: gridaco/spock

Length of output: 171


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '1,200p' /tmp/coderabbit-shell-logs/shell-output-h4JOUV

Repository: gridaco/spock

Length of output: 162


🏁 Script executed:

#!/bin/bash
set -euo pipefail
git ls-files examples/instagram-poc/seed | sed -n '1,200p'

Repository: gridaco/spock

Length of output: 1885


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import re, pathlib
app = pathlib.Path("examples/instagram-poc/app.spock").read_text()
refs = sorted(set(re.findall(r'file\("\./seed/([^"]+)"\)', app)))
seed_dir = pathlib.Path("examples/instagram-poc/seed")
missing = [r for r in refs if not (seed_dir / r).is_file()]
print("\n".join(missing))
PY

Repository: gridaco/spock

Length of output: 153


Missing seed asset reference One referenced file("./seed/…") asset is missing from examples/instagram-poc/seed/, so the seed block will fail to load until the file is added or the path is corrected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/instagram-poc/app.spock` around lines 415 - 800, Audit every
file("./seed/...") reference in the seed block, identify the asset missing from
the examples/instagram-poc/seed collection, and either add that asset or correct
the reference to an existing file. Preserve the intended media mapping for the
associated story, post, carousel slide, or profile field, especially the story
declarations such as lena_story and mira_story.

Comment thread uhura Outdated
@@ -1 +1 @@
Subproject commit 201e847f709738fb75d14a2b6808502cab8f6ebb
Subproject commit 120038e663544933787a28fd5b94d97947cb175f

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

git submodule update --init uhura
git -C uhura cat-file -e 120038e663544933787a28fd5b94d97947cb175f^{commit}
test -d uhura
git -C uhura show --stat --oneline --no-renames 120038e663544933787a28fd5b94d97947cb175f

Repository: gridaco/spock

Length of output: 6752


🏁 Script executed:

#!/bin/bash
set -eu

git ls-files 'scripts/spock-uhura.sh' 'uhura' 'web/package.json' 'examples/instagram-uhura/README.md'
printf '\n--- scripts/spock-uhura.sh ---\n'
cat -n scripts/spock-uhura.sh
printf '\n--- search for uhura artifacts/paths ---\n'
rg -n --hidden --glob '!uhura/.git' --glob '!uhura/**/.git' 'web/dist|dist/spock|canvas-chrome|spock\.js|spock\.ts|launcher|artifact|preview data|uhura.toml' .

Repository: gridaco/spock

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -eu

printf '\n--- scripts/spock-uhura.sh ---\n'
cat -n scripts/spock-uhura.sh

printf '\n--- build-related mentions ---\n'
rg -n --hidden --glob '!uhura/.git' \
  'web/dist|dist/spock|canvas-chrome|spock\.js|spock\.ts|uhura\.toml|preview data|launcher|artifact' \
  scripts web examples README.md .github docs || true

Repository: gridaco/spock

Length of output: 15227


🏁 Script executed:

#!/bin/bash
set -eu

cd uhura

printf '\n--- exact launcher paths at 120038e ---\n'
for path in \
  web/dist/play/index.html \
  web/dist/play/assets \
  crates/uhura-wasm/pkg/web/uhura_wasm.js \
  crates/uhura-wasm/pkg/web/uhura_wasm_bg.wasm \
  examples/instagram-uhura/providers/dist/spock.js \
  web/dist/editor/canvas-chrome.js
do
  printf '\n[%s]\n' "$path"
  git ls-tree -r --name-only 120038e663544933787a28fd5b94d97947cb175f -- "$path" || true
done

printf '\n--- tree presence summary ---\n'
python3 - <<'PY'
import subprocess, sys
paths = [
    "web/dist/play/index.html",
    "web/dist/play/assets",
    "crates/uhura-wasm/pkg/web/uhura_wasm.js",
    "crates/uhura-wasm/pkg/web/uhura_wasm_bg.wasm",
    "examples/instagram-uhura/providers/dist/spock.js",
    "web/dist/editor/canvas-chrome.js",
]
for p in paths:
    out = subprocess.check_output(
        ["git", "ls-tree", "-r", "--name-only", "120038e663544933787a28fd5b94d97947cb175f", "--", p],
        text=True,
    ).strip().splitlines()
    print(f"{p}: {'present' if out else 'absent'}")
PY

Repository: gridaco/spock

Length of output: 905


🏁 Script executed:

#!/bin/bash
set -eu

cd uhura

printf '\n--- uhura/web/README.md (artifacts section) ---\n'
sed -n '40,80p' web/README.md

printf '\n--- uhura/Cargo.toml ---\n'
sed -n '1,40p' Cargo.toml

printf '\n--- build-wasm references ---\n'
rg -n 'build-wasm|pkg/web/uhura_wasm|checked-in web artifacts|generated artifacts are committed|clean checkout' .github README.md web/README.md scripts uhura.toml Cargo.toml examples -g '!**/dist/**' || true

Repository: gridaco/spock

Length of output: 3507


🏁 Script executed:

#!/bin/bash
set -eu

cd uhura

printf '\n--- uhura/web/README.md (artifacts section) ---\n'
sed -n '40,80p' web/README.md

printf '\n--- uhura/Cargo.toml ---\n'
sed -n '1,40p' Cargo.toml

printf '\n--- build-wasm references ---\n'
rg -n 'build-wasm|pkg/web/uhura_wasm|checked-in web artifacts|generated artifacts are committed|clean checkout' .github README.md web/README.md scripts Cargo.toml examples -g '!**/dist/**' || true

Repository: gridaco/spock

Length of output: 3456


Restore the Uhura Wasm bundle expected by scripts/spock-uhura.sh. The submodule commit is present, but uhura/crates/uhura-wasm/pkg/web/uhura_wasm.js and uhura/crates/uhura-wasm/pkg/web/uhura_wasm_bg.wasm are missing here, so a clean checkout will fail the launcher preflight until those artifacts are checked in or the launcher stops requiring them.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@uhura` at line 1, Restore and check in the generated web Wasm artifacts under
the Uhura submodule, specifically uhura_wasm.js and uhura_wasm_bg.wasm expected
by scripts/spock-uhura.sh, or update the launcher’s preflight requirement if
those artifacts are intentionally no longer needed; ensure a clean checkout
passes the launcher preflight.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant